package de.justphil.tcg.tcgserver.rest.resources;

import static de.justphil.tcg.tcgserver.commons.logging.TCGLogging.restLogger;

import java.util.Collection;
import java.util.concurrent.locks.Lock;

import javax.ws.rs.Consumes;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;

import org.slf4j.Logger;

import de.justphil.tcg.tcgserver.commons.config.RestConfig;
import de.justphil.tcg.tcgserver.commons.domain.Card;
import de.justphil.tcg.tcgserver.commons.domain.CardInstance;
import de.justphil.tcg.tcgserver.commons.domain.User;
import de.justphil.tcg.tcgserver.commons.domain.wrappers.FreebieCardReq;
import de.justphil.tcg.tcgserver.commons.domain.wrappers.GeoLocation;
import de.justphil.tcg.tcgserver.commons.domain.wrappers.ListRes;
import de.justphil.tcg.tcgserver.commons.domain.wrappers.ShallowCard;
import de.justphil.tcg.tcgserver.commons.domain.wrappers.SingleObjectRes;
import de.justphil.tcg.tcgserver.commons.exceptions.TCGException;
import de.justphil.tcg.tcgserver.commons.geo.GeoCalculation;
import de.justphil.tcg.tcgserver.commons.grid.Grid;
import de.justphil.tcg.tcgserver.commons.management.Application;
import de.justphil.tcg.tcgserver.commons.management.DataManager;
import de.justphil.tcg.tcgserver.rest.db.image.ImagesDirectory;
import de.justphil.tcg.tcgserver.rest.resources.base.AbstractResource;
import de.justphil.tcg.tcgserver.rest.validators.FreebieCardValidator;



@Path("/card")
public class CardResource extends AbstractResource {
	
	private static final Logger log = restLogger(CardResource.class);
	
	private DataManager dataManager;
	
	public CardResource() {
		dataManager = Application.getDataManager();
	}
	
	
	
	
	
	@GET
	@Path("/{cardId: [0-9]+}")
	@Produces(MediaType.APPLICATION_JSON)
	public Response getCard(@PathParam("cardId") long cardId,
							@HeaderParam(RestConfig.REQ_HEADER_ACCEPT_LANGUAGE) String locale,
							@HeaderParam(RestConfig.REQ_HEADER_AUTHORIZATION) String authHeader) {
		
		/*User user = */
		//aaa(dataManager, locale, authHeader);
		
		log.debug("getCard() cardId => {}", cardId);
		
    	try {
    		Card c = dataManager.getCardById(cardId);
    		
    		ShallowCard cardInfo = new ShallowCard(
    				c.getName(), c.getLife(), c.getAttack(),
    				c.getDefense(), c.getAgility(), c.getPropertyListAsArray()
    		);
    		
    		return ok( new SingleObjectRes<ShallowCard>( cardInfo ) );
    	}
    	catch (TCGException e) {
    		return err(e.getMessage(), (Status) e.getExtra(), locale);
    	}
    }
	
	@GET
    @Path("/{cardId: [0-9]+}/image")
    public Response getCardImage( 	@PathParam("cardId") long cardId,
									@HeaderParam(RestConfig.REQ_HEADER_ACCEPT_LANGUAGE) String locale,
									@HeaderParam(RestConfig.REQ_HEADER_AUTHORIZATION) String authHeader) {
		
		/*User user = */
		//aaa(dataManager, locale, authHeader);
		
		log.debug("getCardImage() cardId => {}", cardId);
		
    	try {
    		byte[] bytes = new ImagesDirectory().getCardImageFile(cardId);
    		
    		return ok(bytes, "image/png");
    	}
    	catch (TCGException e) {
    		return err(e.getMessage(), (Status) e.getExtra(), locale, MediaType.APPLICATION_JSON_TYPE);
    	}
    }
	
	@GET
	@Path("/freebies/{lat}/{lon}/{radius}")
    @Produces(MediaType.APPLICATION_JSON)
	public Response getFreebieCardInstances(@DefaultValue(RestConfig.GEOLOCATION_DEFAULT_VALUE) @PathParam("lat") double lat,
											@DefaultValue(RestConfig.GEOLOCATION_DEFAULT_VALUE) @PathParam("lon") double lon,
											@DefaultValue(RestConfig.GEOLOCATION_DEFAULT_RADIUS) @PathParam("radius") double radius,
											@HeaderParam(RestConfig.REQ_HEADER_ACCEPT_LANGUAGE) String locale,
											@HeaderParam(RestConfig.REQ_HEADER_AUTHORIZATION) String authHeader) {
		/*User user = */
		//aaa(dataManager, locale, authHeader);
		
		try {
			new FreebieCardValidator().validateGet(lat, lon, radius);
			
			GeoLocation[] region = new GeoCalculation().getRegion( new GeoLocation(lat, lon), radius);
			
			Collection<CardInstance> freebies = dataManager.getFreebieCardInstances(region);
			
			return ok( new ListRes<CardInstance>( freebies ) );
		}
		catch (TCGException e) {
			return err(e.getMessage(), (Status) e.getExtra(), locale);
		}
	}
	
	@PUT
	@Path("/freebie/{lat}/{lon}/{ciId: [0-9]+}")
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
	public Response acquireFreebieCardInstances(@DefaultValue(RestConfig.GEOLOCATION_DEFAULT_VALUE) @PathParam("lat") double lat,
												@DefaultValue(RestConfig.GEOLOCATION_DEFAULT_VALUE) @PathParam("lon") double lon,
												@PathParam("ciId") long ciId,
												FreebieCardReq req,
												@HeaderParam(RestConfig.REQ_HEADER_ACCEPT_LANGUAGE) String locale,
												@HeaderParam(RestConfig.REQ_HEADER_AUTHORIZATION) String authHeader) {
		
		log.debug("acquireFreebieCardInstances() lat => {}, lon => {}, ciId => {}", new Object[] { lat, lon, ciId });
		
		User user = aaa(dataManager, locale, authHeader);
		
		Lock lock = Grid.getCardInstanceLock(ciId);
		log.debug("Locking CI {}...", ciId);
		lock.lock();
		log.debug("Locked CI {}!", ciId);
		
		try {
			CardInstance ci = new FreebieCardValidator().validatePut(dataManager, req, lat, lon, ciId);
			
			// Assign user as card instance owner + update all card instance occurrences in the cluster
			dataManager.updateFreebieCardInstanceOwnership(ciId, ci, user);
			
			return ok();
		}
		catch (TCGException e) {
			return err(e.getMessage(), (Status) e.getExtra(), locale);
		}
		finally {
			log.debug("Unlocking CI {}...", ciId);
			lock.unlock();
			log.debug("Unlocked CI {}!", ciId);
		}
	}
	
	
	
	
	
	/*
	@POST
	@Path("/freebies/{lat}/{lon}")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
	public Response getFreebieCardInstances(@DefaultValue(RestConfig.GEOLOCATION_DEFAULT_VALUE) @PathParam("lat") double lat,
											@DefaultValue(RestConfig.GEOLOCATION_DEFAULT_VALUE) @PathParam("lon") double lon,
											FreebieCardReq req,
											@HeaderParam(RestConfig.REQ_HEADER_ACCEPT_LANGUAGE) String locale,
											@HeaderParam(RestConfig.REQ_HEADER_AUTHORIZATION) String authHeader) {
		
		// User user =
		aaa(dataManager, locale, authHeader);
		
		try {
			new FreebieCardValidator().validatePost(req, lat, lon);
			
			GeoLocation[] region = getRegionGeoLocations( new GeoLocation(lat, lon), RestConfig.FREEBIE_RADIUS);
			
			List<FreebieCard> freebies = getFreebieCards(region);
			
			return ok( new FreebieCardListRes( freebies ) );
		}
		catch (TCGException e) {
			return err(e.getMessage(), (Status) e.getExtra(), locale);
		}
	}
	*/
	
	
	
	
	/*
	private Collection<CardInstance> getFreebieCardInstances(GeoLocation[] region) {
		return dataManager.getFreebieCardInstances(region);
	}
	
	
	private List<FreebieCard> getFreebieCards(GeoLocation[] region) {
		Collection<FreebieCard> freebies = dataManager.getFreebieCards(region);
		
		log.debug("freebies.size() => {}", freebies.size());
		
		List<FreebieCard> freebieList = new ArrayList<FreebieCard>(freebies.size());
		for (FreebieCard freebie : freebies) {
			freebieList.add(freebie);
		}
		
		return freebieList;
	}
	*/
	
}